/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package icantalk;

/**
 * A Client class.
 * This class holds information about the client
 * @author orfrenkel
 */
//import com.jeans.trayicon.WindowsTrayIcon;
import javax.swing.*;
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.nio.CharBuffer;

class Client implements ChatConstants,Runnable
{
	/** Holds the socket*/
	private Socket socket;
	private Thread thread;
	/** Holds the data input stream which returns from the socket.*/
	private DataInputStream dis;
	/** Holds the data output stream which returns from the socket.*/
	private DataOutputStream dos;
	/** Implies whether a connection is done.*/ 
	private boolean done=false;
	/** Implies whether there is a connection or not.*/
	private boolean connected = false;
	private MainFrame frame;
	public static String _address;
	/** Holds the user name.*/
	private String username;
	/** Holds information about the user.*/
	private User user;
	

/**
 *  A constructor.
 *  Creates a client with an IP address, and a frame.
 * @throws Exception If an IP address could not be found.
 */
    public Client() throws Exception
    {
		_address = InetAddress.getLocalHost().toString();
		frame = new MainFrame(this);
		
    }

    /** 
     * This method creates a connection to the server 
     * @param server The host name.
     */
	public void connectToServer(String server)
	{
		try	{
			socket = new Socket(server, SERVER_PORT);
			dis = new DataInputStream(socket.getInputStream());
			dos = new DataOutputStream(socket.getOutputStream());
			connected = true;
			thread = new Thread(this,"USER THREAD");
			thread.start();
			
		}
		catch(Exception exception) {
			JOptionPane.showMessageDialog(frame,"Cannot find server !! Please check your settings and try again","Connection error",JOptionPane.ERROR_MESSAGE);
			//WindowsTrayIcon.cleanUp();
			System.exit(-1);
		}

	}
	/**
	 * This method runs the application.
	 *  returns when the connection is dead or signed out. 
	 */
    public void run()
    {
        //System.out.println("USER THREAD STARTED");
        byte[] data;
        while(connected && !done) {
			try {
				processServerMessage();//RECEIVE MESSAGES FROM SERVER
			}
			catch(java.net.SocketException se)
			{
				JOptionPane.showMessageDialog(frame,"Server connection reset!! Please login again","iCanTalk: Error",JOptionPane.ERROR_MESSAGE);
				done = true;
			}
   			catch(NullPointerException se)
			{
				//DO NOTHING
			}
   			catch(java.io.StreamCorruptedException se)
			{
				//DO NOTHING
			}
            catch(Exception e) {
				JOptionPane.showMessageDialog(frame,"Message processing error !!"+e,"iCanTalk: Error",JOptionPane.ERROR_MESSAGE);
				done = true;
			}
	   	}//END WHILE
	   	//IF IT COMES HERE: IT MEANS ERROR
//	   	WindowsTrayIcon.cleanUp();
	   	System.exit(-1);
    }
/**
 * This method takes a massage (without the header), gets a header, and puts them
 * in other method to send the massage to the server.  
 * @param message The massage which is sent.
 * @throws java.io.IOException If an I/O error.
 */
    public void sendMessageToServer(String message) throws java.io.IOException
    {

		sendMessageToServer(new Message(PUBLIC_CHAT,message));
	}
    /**
     * This method sends a massage to the server.
     * @param message The string massage with a header.
     * @throws java.io.IOException If an I/O error.
     */
	public void sendMessageToServer(Message message) throws java.io.IOException
	{
		byte[] data;
		//PACK THE USERNAME AND HOST ADDRESS EVERYTIME
		message._username = username;
		message._host = _address;
      	data = ChatUtils.objectToBytes(message);
		dos.write(data,0,data.length);
		dos.flush();
	}
/**
 * This method sends a file to the server.
 * @param message The file with the header.
 * @throws java.io.IOException If an I/O error.
 */
	public void sendFileToServer(Message message) throws java.io.IOException
	{
		byte[] data;
		//PACK THE USERNAME AND HOST ADDRESS EVERYTIME
		
		message._username = username;
		message._host = _address;
		message._message = "";
		
		Message tempMessage = (Message)message;
		
		try{
			// Open the file that is the first 
			// command line parameter
			FileInputStream fstream = new FileInputStream(message._data.toString());
			// Get the object of DataInputStream
			DataInputStream in = new DataInputStream(fstream);
			BufferedReader br = new BufferedReader(new InputStreamReader(in));
			String strLine;
			int i = 0;
			//Read File Line By Line
			
			
			int buffLength = -1;
			do
			{
				message = new Message(tempMessage);
			    
			//    System.out.println(message._message);
			    
			    CharBuffer buff = CharBuffer.allocate( (MAX_MESSAGE_SIZE - ChatUtils.objectToBytes(message).length ) / 2);
				
			    buffLength = br.read(buff);

			    if ( buffLength == -1 )
			    {
			    	message._message = "";
			    }
			    else
			    {
			    	message._message = String.copyValueOf(buff.array());
			    }
			    
			    
			    data = ChatUtils.objectToBytes(message);
			    
//			    if ( data.length >= MAX_MESSAGE_SIZE )
//			    {
//			    	buffLength = buffLength + 1 - 1;
//			    }
			    
		    	dos.write(data,0,data.length);
		    	dos.flush();
		    	
		    	Thread.sleep(100);
		    	
			}while ( buffLength != -1);  
			
			/*while ( buffLength != -1)   {
				// Print the content on the console
				message = new Message(tempMessage);
			    
			    message._message = String.copyValueOf(buff.array());
			//    System.out.println(message._message);
				
			    System.out.println(i++);
			    if (i == 13 )
			    {
			    	i = 13;
			    }
		    	data = ChatUtils.objectToBytes(message);
		    	dos.write(data,0,data.length);
		    	dos.flush();
		    	
		    	Thread.sleep(1000);
		    	
			}*/
			
			/*message = new Message(tempMessage);
		    message._message = "";
		    System.out.println(i++);
		    
		    data = ChatUtils.objectToBytes(message);
	    	dos.write(data,0,data.length);
	    	dos.flush();
			*/
			//Close the input stream
			in.close();
		}catch (Exception e){//Catch exception if any
			System.err.println("Error: " + e.getMessage());
		}
	}
	/**
	 * 
	 * @throws java.io.IOException If an I/O error.
	 * @throws java.net.SocketException If a socket error
	 * @throws Exception
	 */
	public void processServerMessage() throws java.io.IOException,
											java.net.SocketException,Exception
	{
		
		byte[] data;
    	data = new byte[MAX_MESSAGE_SIZE];
		dis.read(data);
		Message message = (Message)ChatUtils.bytesToObject(data);
		frame.processServerMessage(message);
		
	}
/**
 * Sets the user
 * @param user A user information.
 */
	public void setUser(User user)
	{
		this.username = user.toString();
		this.user = user;
	}
/**
 * 
 * @param args
 * @throws Exception
 */
	public static void main(String args[]) throws Exception
    {
		SplashScreen screen = new SplashScreen(3000);
  		Client myclient = new Client();
    }
}


